/**
  ******************************************************************************
  * @file    WIZnet MDK5 Project Template  ../main.c 
  * @author  WIZnet Software Team
  * @version V1.0.0
  * @date    2018-09-25
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2018 WIZnet H.K. Ltd.</center></h2>
  ******************************************************************************
  */  

/* Includes ------------------------------------------------------------------*/
#include <stddef.h>
#include "./usart/bsp_usart_debug.h"

#include "wizchip_conf.h"
#include <string.h>
#include <stdio.h>
#include "dhcp.h"
#include "delay.h"
#include "BKP.h"

void dhcp_timer_init(void)
{
  //timer2_init();																	
}

// 添加缺失的全局变量定义
uint8_t dhcp_ok = 0;        // DHCP状态标志
uint8_t ip_from = 0;        // IP配置方法
uint32_t dhcp_time = 0;     // DHCP时间计数器

uint8_t mac[6]={0x01,0x02,0xab,0xcd,0x10,0x01};

uint8_t l_ip[4]  ={192,168,3,24};				// mcu ip
uint8_t subnet[4]    ={255,255,255,0};		// mask
uint8_t gw[4]   ={192,168,3,1};				   // gw
uint8_t l_dns[4]={114,114,114,114};		      // dns


uint16_t l_port = 80;


uint8_t des_ip[4] = {192,168,3,102};        // 远端ip地址
uint16_t des_port = 8080;                                   // 远端port

wiz_NetInfo  NetInfo;			
uint8_t	ip_stat = DEFINE;



void reset_w5500(void)
{
    printf("Resetting W5500...\r\n");
    GPIO_ResetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET);
    delay_ms(200);  // 复位时间200ms
    GPIO_SetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET);
    delay_ms(3000); // 复位后等待3秒
    printf("W5500 reset completed\r\n");
    
    // 添加软件复位
    printf("执行软件复位...\r\n");
    setMR(MR_RST);
    delay_ms(100);
    printf("软件复位完成\r\n");
}






void set_w5500_ip(void)
{	    
    /*复制定义的配置信息到配置结构体*/
	memcpy(NetInfo.mac, mac, 6);
	memcpy(NetInfo.ip,l_ip,4);
	memcpy(NetInfo.sn,subnet,4);
	memcpy(NetInfo.gw,gw,4);
	memcpy(NetInfo.dns,l_dns,4);
   if(ip_stat == DEFINE)
   {
      printf(" 使用定义的IP信息配置W5500\r\n");
   }else if(ip_stat == GPR)
   {
		 if(get_bkp_stat(mac)){
			 get_bkp_mac(&NetInfo);
			 get_bkp_ip(&NetInfo);
			 get_bkp_mask(&NetInfo);
			 get_bkp_gw(&NetInfo);
			 get_bkp_dns(&NetInfo);
		 }
      // 使用备份域寄存器获取 函数
      // 读ip dns gw sn mac等 用mac去对撞获取数据
      printf(" 使用GPR备份域寄存器获取IP信息配置W5500\r\n");
      // 如果今存其为空 则使用定义的IP信息配置W5500然后存入寄存器
   }else if(ip_stat == DHCP)
   {
     if(dhcp_ok==1)
		{
			printf(" IP from DHCP\r\n");		 
			memcpy(NetInfo.ip,DHCP_GET.lip, 4);
			memcpy(NetInfo.sn,DHCP_GET.sub, 4);
			memcpy(NetInfo.gw,DHCP_GET.gw, 4);
			memcpy(NetInfo.dns,DHCP_GET.dns,4);
		}
		else
		{
			printf(" DHCP子程序未运行,或者不成功\r\n");
			printf(" 使用定义的IP信息配置W5500\r\n");
			set_bkp_mac(NetInfo);
			set_bkp_ip(NetInfo);
			set_bkp_mask(NetInfo);
			set_bkp_gw(NetInfo);
			set_bkp_dns(NetInfo);
		}
   }

	/*将IP配置信息写入W5500相应寄存器*/	
	setSUBR(NetInfo.sn);
	 delay_ms(10); 
	setGAR(NetInfo.gw);
	 delay_ms(10); 
	setSIPR(NetInfo.ip);
	delay_ms(10); 
	getSIPR (l_ip);			
	printf(" W5500 IP地址   : %d.%d.%d.%d\r\n", l_ip[0],l_ip[1],l_ip[2],l_ip[3]);
	getSUBR(subnet);
	printf(" W5500 子网掩码 : %d.%d.%d.%d\r\n", subnet[0],subnet[1],subnet[2],subnet[3]);
	getGAR(gw);
	printf(" W5500 网关     : %d.%d.%d.%d\r\n", gw[0],gw[1],gw[2],gw[3]);
	 
	 
}


void mac_set()
{
   memcpy(NetInfo.mac, mac, 6);
	setSHAR(NetInfo.mac);	/**/
	memcpy(DHCP_GET.mac, mac, 6);
}

void gpio_for_w5500_config(void)
{
		SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    
    printf("Initializing W5500 GPIO and SPI...\r\n");
    
    // 使能GPIO时钟
    RCC_AHB1PeriphClockCmd(WIZ_SPIx_RESET_CLK | WIZ_SPIx_INT_CLK, ENABLE);
    RCC_AHB1PeriphClockCmd(WIZ_SPIx_GPIO_CLK | WIZ_SPIx_SCS_CLK, ENABLE);
    
    // 使能SPI时钟
    RCC_APB2PeriphClockCmd(WIZ_SPIx_CLK, ENABLE);
    
    // 配置SPI引脚: SCK, MISO, MOSI
    GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_SCLK | WIZ_SPIx_MISO | WIZ_SPIx_MOSI;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure);
    
    // 配置AF功能
    GPIO_PinAFConfig(WIZ_SPIx_GPIO_PORT, GPIO_PinSource5, GPIO_AF_SPI1); // SCK
    GPIO_PinAFConfig(WIZ_SPIx_GPIO_PORT, GPIO_PinSource6, GPIO_AF_SPI1); // MISO
    GPIO_PinAFConfig(WIZ_SPIx_GPIO_PORT, GPIO_PinSource7, GPIO_AF_SPI1); // MOSI
    
    // 配置片选引脚(CS)
    GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_SCS;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(WIZ_SPIx_SCS_PORT, &GPIO_InitStructure);
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); // CS默认高电平（不选中）
    
    // 配置复位引脚(RESET)
    GPIO_InitStructure.GPIO_Pin = WIZ_RESET;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(WIZ_SPIx_RESET_PORT, &GPIO_InitStructure);
    GPIO_SetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET); // 复位默认高电平（不复位）
    
    // 配置中断引脚(INT)
    GPIO_InitStructure.GPIO_Pin = WIZ_INT;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉输入
    GPIO_Init(WIZ_SPIx_INT_PORT, &GPIO_InitStructure);
    
    // SPI配置 - W5500 需要 SPI Mode 3
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    
    // W5500要求：CPOL=1, CPHA=1 (Mode 3)
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;    // 空闲时时钟为高
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   // 修正：应该是2Edge！
    
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // 适中速度
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    printf("W5500 GPIO and SPI initialized successfully\r\n");
    printf("SPI Mode: CPOL=High, CPHA=2Edge (Mode 3)\r\n");
    printf("SPI Speed: %d Hz\r\n", SystemCoreClock / 64);
}


/**
 * @brief Default function to enable interrupt.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
void 	  wizchip_cris_enter(void)           {};
/**
 * @brief Default function to disable interrupt.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
void 	  wizchip_cris_exit(void)          {};
/**
 * @brief Default function to select chip.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */

 void iinchip_csoff(void);
void wizchip_cs_select(void)            
{
   iinchip_csoff();  // CS 拉低，选中芯片
}
/**
 * @brief Default function to deselect chip.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
void iinchip_cson(void);
void wizchip_cs_deselect(void)          
{
   iinchip_cson();   // CS 拉高，取消选中芯片
}
/**
 * @brief Default function to read in direct or indirect interface.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
 //M20140501 : Explict pointer type casting
//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); };
uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); };
/**
 * @brief Default function to write in direct or indirect interface.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
 
//M20140501 : Explict pointer type casting
//void 	wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb)  { *((volatile uint8_t*) AddrSel) = wb; };
void 	wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb)  { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; };


uint8_t  IINCHIP_SpiSendData(uint8 dat);

/**
 * @brief Default function to read in SPI interface.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
uint8_t wizchip_spi_readbyte(void)        
{
   return IINCHIP_SpiSendData(0x00);  // 发送0x00并接收数据
}

/**
 * @brief Default function to write in SPI interface.
 * @note This function help not to access wrong address. If you do not describe this function or register any functions,
 * null function is called.
 */
void wizchip_spi_writebyte(uint8_t wb) 
{
   IINCHIP_SpiSendData(wb);  // 发送数据
}

/**
 * @\ref _WIZCHIP instance
 */
_WIZCHIP  WIZCHIP =
      {
      .id                  = _WIZCHIP_ID_,
      .if_mode             = _WIZCHIP_IO_MODE_,
      .CRIS._enter         = wizchip_cris_enter,
      .CRIS._exit          = wizchip_cris_exit,
      .CS._select          = wizchip_cs_select,
      .CS._deselect        = wizchip_cs_deselect,
      .IF.BUS._read_byte   = wizchip_bus_readbyte,
      .IF.BUS._write_byte  = wizchip_bus_writebyte,
      .IF.SPI._read_byte   = wizchip_spi_readbyte,
      .IF.SPI._write_byte  = wizchip_spi_writebyte
      };

static uint8_t    _DNS_[4];      // DNS server ip address
static dhcp_mode  _DHCP_;        // DHCP mode

void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
{
   if(!cris_en || !cris_ex)
   {
      WIZCHIP.CRIS._enter = wizchip_cris_enter;
      WIZCHIP.CRIS._exit  = wizchip_cris_exit;
   }
   else
   {
      WIZCHIP.CRIS._enter = cris_en;
      WIZCHIP.CRIS._exit  = cris_ex;
   }
}

void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
{
   if(!cs_sel || !cs_desel)
   {
      WIZCHIP.CS._select   = wizchip_cs_select;
      WIZCHIP.CS._deselect = wizchip_cs_deselect;
   }
   else
   {
      WIZCHIP.CS._select   = cs_sel;
      WIZCHIP.CS._deselect = cs_desel;
   }
}

void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
{
   while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
   
   if(!bus_rb || !bus_wb)
   {
      WIZCHIP.IF.BUS._read_byte   = wizchip_bus_readbyte;
      WIZCHIP.IF.BUS._write_byte  = wizchip_bus_writebyte;
   }
   else
   {
      WIZCHIP.IF.BUS._read_byte   = bus_rb;
      WIZCHIP.IF.BUS._write_byte  = bus_wb;
   }
}

void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
{
   while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
   
   if(!spi_rb || !spi_wb)
   {
      WIZCHIP.IF.SPI._read_byte   = wizchip_spi_readbyte;
      WIZCHIP.IF.SPI._write_byte  = wizchip_spi_writebyte;
   }
   else
   {
      WIZCHIP.IF.SPI._read_byte   = spi_rb;
      WIZCHIP.IF.SPI._write_byte  = spi_wb;
   }
}

int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
{
   uint8_t tmp = 0;
   uint8_t* ptmp[2] = {0,0};
   switch(cwtype)
   {
      case CW_RESET_WIZCHIP:
         wizchip_sw_reset();
         break;
      case CW_INIT_WIZCHIP:
         if(arg != 0) 
         {
            ptmp[0] = (uint8_t*)arg;
            ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
         }
         return wizchip_init(ptmp[0], ptmp[1]);
      case CW_CLR_INTERRUPT:
         wizchip_clrinterrupt(*((intr_kind*)arg));
         break;
      case CW_GET_INTERRUPT:
        *((intr_kind*)arg) = wizchip_getinterrupt();
         break;
      case CW_SET_INTRMASK:
         wizchip_setinterruptmask(*((intr_kind*)arg));
         break;         
      case CW_GET_INTRMASK:
         *((intr_kind*)arg) = wizchip_getinterruptmask();
         break;
   #if _WIZCHIP_ > 5100
      case CW_SET_INTRTIME:
         setINTLEVEL(*(uint16_t*)arg);
         break;
      case CW_GET_INTRTIME:
         *(uint16_t*)arg = getINTLEVEL();
         break;
   #endif
      case CW_GET_ID:
         ((uint8_t*)arg)[0] = WIZCHIP.id[0];
         ((uint8_t*)arg)[1] = WIZCHIP.id[1];
         ((uint8_t*)arg)[2] = WIZCHIP.id[2];
         ((uint8_t*)arg)[3] = WIZCHIP.id[3];
         ((uint8_t*)arg)[4] = WIZCHIP.id[4];
         ((uint8_t*)arg)[5] = 0;
         break;
   #if _WIZCHIP_ ==  5500
      case CW_RESET_PHY:
         wizphy_reset();
         break;
      case CW_SET_PHYCONF:
         wizphy_setphyconf((wiz_PhyConf*)arg);
         break;
      case CW_GET_PHYCONF:
         wizphy_getphyconf((wiz_PhyConf*)arg);
         break;
      case CW_GET_PHYSTATUS:
         break;
      case CW_SET_PHYPOWMODE:
         return wizphy_setphypmode(*(uint8_t*)arg);
   #endif
      case CW_GET_PHYPOWMODE:
         tmp = wizphy_getphypmode();
         if((int8_t)tmp == -1) return -1;
         *(uint8_t*)arg = tmp;
         break;
      case CW_GET_PHYLINK:
         tmp = wizphy_getphylink();
         if((int8_t)tmp == -1) return -1;
         *(uint8_t*)arg = tmp;
         break;
      default:
         return -1;
   }
   return 0;
}


int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
{
   switch(cntype)
   {
      case CN_SET_NETINFO:
         wizchip_setnetinfo((wiz_NetInfo*)arg);
         break;
      case CN_GET_NETINFO:
         wizchip_getnetinfo((wiz_NetInfo*)arg);
         break;
      case CN_SET_NETMODE:
         return wizchip_setnetmode(*(netmode_type*)arg);
      case CN_GET_NETMODE:
         *(netmode_type*)arg = wizchip_getnetmode();
         break;
      case CN_SET_TIMEOUT:
         wizchip_settimeout((wiz_NetTimeout*)arg);
         break;
      case CN_GET_TIMEOUT:
         wizchip_gettimeout((wiz_NetTimeout*)arg);
         break;
      default:
         return -1;
   }
   return 0;
}

void wizchip_sw_reset(void)
{
   uint8_t gw[4], sn[4], sip[4];
   uint8_t mac[6];
   getSHAR(mac);
   getGAR(gw);  getSUBR(sn);  getSIPR(sip);
   setMR(MR_RST);
   getMR(); // for delay
   setSHAR(mac);
   setGAR(gw);
   setSUBR(sn);
   setSIPR(sip);
}

int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
{
   int8_t i;
   int8_t tmp = 0;
   wizchip_sw_reset();
   if(txsize)
   {
      tmp = 0;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         tmp += txsize[i];
      if(tmp > 16) return -1;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         setSn_TXBUF_SIZE(i, txsize[i]);
   }
   if(rxsize)
   {
      tmp = 0;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         tmp += rxsize[i];
      if(tmp > 16) return -1;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         setSn_RXBUF_SIZE(i, rxsize[i]);
   }
   return 0;
}

void wizchip_clrinterrupt(intr_kind intr)
{
   uint8_t ir  = (uint8_t)intr;
   uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < 5500
   ir |= (1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
   ir |= (1 << 6);
#endif
   
#if _WIZCHIP_ < 5200
   sir &= 0x0F;
#endif

#if _WIZCHIP_ == 5100
   ir |= sir;
   setIR(ir);
#else
   setIR(ir);
   setSIR(sir);
#endif   
}

intr_kind wizchip_getinterrupt(void)
{
   uint8_t ir  = 0;
   uint8_t sir = 0;
   uint16_t ret = 0;
#if _WIZCHIP_ == 5100
   ir = getIR();
   sir = ir 0x0F;
#else
   ir  = getIR();
   sir = getSIR();
#endif         

#if _WIZCHIP_ < 5500
   ir &= ~(1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
   ir &= ~(1 << 6);
#endif
  ret = sir;
  ret = (ret << 8) + ir;
  return (intr_kind)ret;
}

void wizchip_setinterruptmask(intr_kind intr)
{
   uint8_t imr  = (uint8_t)intr;
   uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < 5500
   imr &= ~(1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
   imr &= ~(1 << 6);
#endif
   
#if _WIZCHIP_ < 5200
   simr &= 0x0F;
#endif

#if _WIZCHIP_ == 5100
   imr |= simr;
   setIMR(imr);
#else
   setIMR(imr);
   setSIMR(simr);
#endif   
}

intr_kind wizchip_getinterruptmask(void)
{
   uint8_t imr  = 0;
   uint8_t simr = 0;
   uint16_t ret = 0;
#if _WIZCHIP_ == 5100
   imr  = getIMR();
   simr = imr 0x0F;
#else
   imr  = getIMR();
   simr = getSIMR();
#endif         

#if _WIZCHIP_ < 5500
   imr &= ~(1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
   imr &= ~(1 << 6);  // IK_DEST_UNREACH
#endif
  ret = simr;
  ret = (ret << 8) + imr;
  return (intr_kind)ret;
}

int8_t wizphy_getphylink(void)
{
   int8_t tmp;
#if   _WIZCHIP_ == 5200
   if(getPHYSTATUS() & PHYSTATUS_LINK)
      tmp = PHY_LINK_ON;
   else
      tmp = PHY_LINK_OFF;
#elif _WIZCHIP_ == 5500
   if(getPHYCFGR() & PHYCFGR_LNK_ON)
      tmp = PHY_LINK_ON;
   else
      tmp = PHY_LINK_OFF;
#else
   tmp = -1;
#endif
   return tmp;
}

#if _WIZCHIP_ > 5100

int8_t wizphy_getphypmode(void)
{
   int8_t tmp = 0;
   #if   _WIZCHIP_ == 5200
      if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
         tmp = PHY_POWER_DOWN;
      else          
         tmp = PHY_POWER_NORM;
   #elif _WIZCHIP_ == 5500
      if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN)
         tmp = PHY_POWER_DOWN;
      else 
         tmp = PHY_POWER_NORM;
   #else
      tmp = -1;
   #endif
   return tmp;
}
#endif

#if _WIZCHIP_ == 5500
void wizphy_reset(void)
{
   uint8_t tmp = getPHYCFGR();
   tmp &= PHYCFGR_RST;
   setPHYCFGR(tmp);
   tmp = getPHYCFGR(); 
   tmp |= ~PHYCFGR_RST;
   setPHYCFGR(tmp);
}

void wizphy_setphyconf(wiz_PhyConf* phyconf)
{
   uint8_t tmp = 0;
   if(phyconf->by == PHY_CONFBY_SW)
      tmp |= PHYCFGR_OPMD;
   else
      tmp &= ~PHYCFGR_OPMD;
   if(phyconf->mode == PHY_MODE_AUTONEGO)
      tmp |= PHYCFGR_OPMDC_ALLA;
   else
   {
      if(phyconf->duplex == PHY_DUPLEX_FULL)
      {
         if(phyconf->speed == PHY_SPEED_100)
            tmp |= PHYCFGR_OPMDC_100F;
         else
            tmp |= PHYCFGR_OPMDC_10F;
      }   
      else
      {
         if(phyconf->speed == PHY_SPEED_100)
            tmp |= PHYCFGR_OPMDC_100H;
         else
            tmp |= PHYCFGR_OPMDC_10H;
      }
   }
   setPHYCFGR(tmp);
   wizphy_reset();
}

void wizphy_getphyconf(wiz_PhyConf* phyconf)
{
   uint8_t tmp = 0;
   tmp = getPHYCFGR();
   phyconf->by   = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
   switch(tmp & PHYCFGR_OPMDC_ALLA)
   {
      case PHYCFGR_OPMDC_ALLA:
      case PHYCFGR_OPMDC_100FA: 
         phyconf->mode = PHY_MODE_AUTONEGO;
         break;
      default:
         phyconf->mode = PHY_MODE_MANUAL;
         break;
   }
   switch(tmp & PHYCFGR_OPMDC_ALLA)
   {
      case PHYCFGR_OPMDC_100FA:
      case PHYCFGR_OPMDC_100F:
      case PHYCFGR_OPMDC_100H:
         phyconf->speed = PHY_SPEED_100;
         break;
      default:
         phyconf->speed = PHY_SPEED_10;
         break;
   }
   switch(tmp & PHYCFGR_OPMDC_ALLA)
   {
      case PHYCFGR_OPMDC_100FA:
      case PHYCFGR_OPMDC_100F:
      case PHYCFGR_OPMDC_10F:
         phyconf->duplex = PHY_DUPLEX_FULL;
         break;
      default:
         phyconf->duplex = PHY_DUPLEX_HALF;
         break;
   }
}

void wizphy_getphystat(wiz_PhyConf* phyconf)
{
   uint8_t tmp = getPHYCFGR();
   phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
   phyconf->speed  = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
}

int8_t wizphy_setphypmode(uint8_t pmode)
{
   uint8_t tmp = 0;
   tmp = getPHYCFGR();
   if((tmp & PHYCFGR_OPMD)== 0) return -1;
   tmp &= ~PHYCFGR_OPMDC_ALLA;         
   if( pmode == PHY_POWER_DOWN)
      tmp |= PHYCFGR_OPMDC_PDOWN;
   else
      tmp |= PHYCFGR_OPMDC_ALLA;
   setPHYCFGR(tmp);
   wizphy_reset();
   tmp = getPHYCFGR();
   if( pmode == PHY_POWER_DOWN)
   {
      if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
   }
   else
   {
      if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
   }
   return -1;
}
#endif


void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
{
   setSHAR(pnetinfo->mac);
   setGAR(pnetinfo->gw);
   setSUBR(pnetinfo->sn);
   setSIPR(pnetinfo->ip);
   _DNS_[0] = pnetinfo->dns[0];
   _DNS_[1] = pnetinfo->dns[1];
   _DNS_[2] = pnetinfo->dns[2];
   _DNS_[3] = pnetinfo->dns[3];
   _DHCP_   = pnetinfo->dhcp;
}

void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
{
   getSHAR(pnetinfo->mac);
   getGAR(pnetinfo->gw);
   getSUBR(pnetinfo->sn);
   getSIPR(pnetinfo->ip);
   pnetinfo->dns[0]= _DNS_[0];
   pnetinfo->dns[1]= _DNS_[1];
   pnetinfo->dns[2]= _DNS_[2];
   pnetinfo->dns[3]= _DNS_[3];
   pnetinfo->dhcp  = _DHCP_;
}

int8_t wizchip_setnetmode(netmode_type netmode)
{
   uint8_t tmp = 0;
#if _WIZCHIP_ != 5500   
   if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
#else
   if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
#endif      
   tmp = getMR();
   tmp |= (uint8_t)netmode;
   setMR(tmp);
   return 0;
}

netmode_type wizchip_getnetmode(void)
{
   return (netmode_type) getMR();
}

void wizchip_settimeout(wiz_NetTimeout* nettime)
{
   setRCR(nettime->retry_cnt);
   setRTR(nettime->time_100us);
}

void wizchip_gettimeout(wiz_NetTimeout* nettime)
{
   nettime->retry_cnt = getRCR();
   nettime->time_100us = getRTR();
}

void wiz_cs(uint8_t val)
{
	if (val == 0) 
	{
	  GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); 
		delay_us(1);
	}
	else if (val == 1)
	{
		delay_us(1);
	  GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); 
	}
}

void iinchip_csoff(void)
{
	wiz_cs(0);
}

uint8_t SPI_SendByte(uint8_t byte)
{
    /* Loop while DR register in not emplty */
    while (SPI_I2S_GetFlagStatus(WIZ_SPIx, SPI_I2S_FLAG_TXE) == RESET);

    /* Send byte through the SPI1 peripheral */
    SPI_I2S_SendData(WIZ_SPIx, byte);
    
    delay_us(10); // 减少延时

    /* Wait to receive a byte */
    while (SPI_I2S_GetFlagStatus(WIZ_SPIx, SPI_I2S_FLAG_RXNE) == RESET);

    /* Return the byte read from the SPI bus */
    return SPI_I2S_ReceiveData(WIZ_SPIx);
}

uint8_t  IINCHIP_SpiSendData(uint8 dat)
{
   return(SPI_SendByte(dat));
}
void iinchip_cson(void)
{	
   wiz_cs(1);
}
void IINCHIP_WRITE( uint32 addrbsb,  uint8 data)
{
   iinchip_csoff();                              		
   IINCHIP_SpiSendData( (addrbsb & 0x00FF0000)>>16);	
   IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);
   IINCHIP_SpiSendData( (addrbsb & 0x000000F8) + 4);  
   IINCHIP_SpiSendData(data);                   
   iinchip_cson();                            
}

uint8_t IINCHIP_READ(uint32 addrbsb)
{
   uint8 data = 0;
   iinchip_csoff();                            
   IINCHIP_SpiSendData( (addrbsb & 0x00FF0000)>>16);  // 地址高字节
   IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);  // 地址中字节
   IINCHIP_SpiSendData( (addrbsb & 0x000000F8))    ;  // 地址低字节
   data = IINCHIP_SpiSendData(0x00);                 // 读取数据
   iinchip_cson();                               
   return data;    
}

uint16_t wiz_write_buf(uint32_t addrbsb,uint8_t* buf,uint16_t len)
{
   uint16 idx = 0;
   if(len == 0) printf("Unexpected2 length 0\r\n");
   iinchip_csoff();                               
   IINCHIP_SpiSendData( (addrbsb & 0x00FF0000)>>16);
   IINCHIP_SpiSendData( (addrbsb & 0x0000FF00)>> 8);
   IINCHIP_SpiSendData( (addrbsb & 0x000000F8) + 4); 
   for(idx = 0; idx < len; idx++)
   {
     IINCHIP_SpiSendData(buf[idx]);
   }
   iinchip_cson();                           
   return len;  
}

// 在文件末尾添加测试函数
void test_w5500_spi_communication(void)
{
    uint8_t test_data[4] = {0};
    
    printf("Testing W5500 SPI communication...\r\n");
    
    // 测试读取 W5500 版本寄存器 (应该返回 0x04)
    uint8_t version = IINCHIP_READ(VERSIONR);
    printf("W5500 Version: 0x%02X\r\n", version);
    
    // 测试读取源IP寄存器
    printf("Reading SIPR register...\r\n");
    getSIPR(test_data);
    printf("SIPR: %d.%d.%d.%d\r\n", test_data[0], test_data[1], test_data[2], test_data[3]);
    
    // 测试读取子网掩码寄存器
    printf("Reading SUBR register...\r\n");
    getSUBR(test_data);
    printf("SUBR: %d.%d.%d.%d\r\n", test_data[0], test_data[1], test_data[2], test_data[3]);
    
    // 测试读取网关寄存器
    printf("Reading GAR register...\r\n");
    getGAR(test_data);
    printf("GAR: %d.%d.%d.%d\r\n", test_data[0], test_data[1], test_data[2], test_data[3]);
}

// 添加更详细的测试函数
void test_w5500_detailed(void)
{
    uint8_t test_data[4] = {0};
    
    printf("=== W5500 Detailed Test ===\r\n");
    
    // 测试版本寄存器
    printf("Testing version register...\r\n");
    uint8_t version = IINCHIP_READ(VERSIONR);
    printf("Version: 0x%02X (expected: 0x04)\r\n", version);
    
    if (version == 0x04) {
        printf("✓ W5500 communication successful!\r\n");
        
        // 测试其他寄存器
        getSIPR(test_data);
        printf("SIPR: %d.%d.%d.%d\r\n", test_data[0], test_data[1], test_data[2], test_data[3]);
        
        getSUBR(test_data);
        printf("SUBR: %d.%d.%d.%d\r\n", test_data[0], test_data[1], test_data[2], test_data[3]);
        
        getGAR(test_data);
        printf("GAR: %d.%d.%d.%d\r\n", test_data[0], test_data[1], test_data[2], test_data[3]);
    } else {
        printf("✗ W5500 communication failed!\r\n");
        printf("Version = 0x%02X (all 0xFF indicates no response)\r\n", version);
    }
    printf("=== End Test ===\r\n");
}

// 添加这个简单的测试函数
void test_basic_spi_communication(void)
{
    printf("=== Basic SPI Communication Test ===\r\n");
    
    // 测试 1: 发送简单的数据并查看响应
    printf("Test 1: Sending 0xAA and checking response...\r\n");
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); // CS 拉低
    delay_us(10);
    
    uint8_t sent = 0xAA;
    uint8_t received = SPI_SendByte(sent);
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); // CS 拉高
    
    printf("Sent: 0x%02X, Received: 0x%02X\r\n", sent, received);
    
    // 测试 2: 测试版本寄存器读取
    printf("\nTest 2: Reading version register...\r\n");
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_us(10);
    
    // 发送版本寄存器地址: 0x003900
    uint8_t addr_high = 0x00;
    uint8_t addr_mid = 0x39;
    uint8_t addr_low = 0x00;
    uint8_t dummy = 0x00;
    
    uint8_t resp1 = SPI_SendByte(addr_high);
    uint8_t resp2 = SPI_SendByte(addr_mid);
    uint8_t resp3 = SPI_SendByte(addr_low);
    uint8_t resp4 = SPI_SendByte(dummy);
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    
    printf("Address: 0x%02X%02X%02X\r\n", addr_high, addr_mid, addr_low);
    printf("Responses: 0x%02X, 0x%02X, 0x%02X, 0x%02X\r\n", resp1, resp2, resp3, resp4);
    printf("Version should be: 0x04\r\n");
    
    if (resp4 == 0x04) {
        printf("✓ W5500 communication successful!\r\n");
    } else {
        printf("✗ W5500 communication failed!\r\n");
        printf("Possible issues:\r\n");
        printf("1. W5500 not powered properly\r\n");
        printf("2. SPI wiring issues\r\n");
        printf("3. W5500 not responding (hardware fault)\r\n");
    }
    
    printf("=== Test Complete ===\r\n");
}

// 修正后的深度诊断函数
void deep_hardware_diagnosis(void)
{
    SPI_InitTypeDef SPI_InitStructure; // 添加这个变量声明
    
    printf("=== Deep Hardware Diagnosis ===\r\n");
    
    // 1. 检查所有引脚状态
    printf("1. Checking all GPIO states...\r\n");
    printf("   SCS (PA4): %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS));
    printf("   RST (PB7): %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_RESET_PORT, WIZ_RESET));
    printf("   INT (PB8): %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_INT_PORT, WIZ_INT));
    printf("   SCLK (PA5): %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_GPIO_PORT, WIZ_SPIx_SCLK));
    printf("   MISO (PA6): %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_GPIO_PORT, WIZ_SPIx_MISO));
    printf("   MOSI (PA7): %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_GPIO_PORT, WIZ_SPIx_MOSI));
    
    // 2. 测试 SPI 硬件回环
    printf("\n2. Testing SPI hardware loopback...\r\n");
    printf("   (This tests if SPI hardware is working at all)\r\n");
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_us(10);
    
    uint8_t test_data[] = {0x55, 0xAA, 0x33, 0xCC};
    uint8_t received_data[4];
    
    for(int i = 0; i < 4; i++) {
        received_data[i] = SPI_SendByte(test_data[i]);
        printf("   Sent: 0x%02X, Received: 0x%02X\r\n", test_data[i], received_data[i]);
    }
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    
    // 3. 测试不同的 SPI 配置
    printf("\n3. Testing different SPI configurations...\r\n");
    
    // 初始化 SPI 结构体
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    
    // 测试 SPI Mode 0
    printf("   Testing SPI Mode 0 (CPOL=0, CPHA=1Edge)...\r\n");
    SPI_Cmd(WIZ_SPIx, DISABLE);
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_us(10);
    
    uint8_t mode0_result = 0;
    SPI_SendByte(0x00);
    SPI_SendByte(0x39);
    SPI_SendByte(0x00);
    mode0_result = SPI_SendByte(0x00);
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    printf("   Mode 0 result: 0x%02X\r\n", mode0_result);
    
    // 测试 SPI Mode 1
    printf("   Testing SPI Mode 1 (CPOL=0, CPHA=2Edge)...\r\n");
    SPI_Cmd(WIZ_SPIx, DISABLE);
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_us(10);
    
    uint8_t mode1_result = 0;
    SPI_SendByte(0x00);
    SPI_SendByte(0x39);
    SPI_SendByte(0x00);
    mode1_result = SPI_SendByte(0x00);
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    printf("   Mode 1 result: 0x%02X\r\n", mode1_result);
    
    // 测试 SPI Mode 2
    printf("   Testing SPI Mode 2 (CPOL=1, CPHA=1Edge)...\r\n");
    SPI_Cmd(WIZ_SPIx, DISABLE);
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_us(10);
    
    uint8_t mode2_result = 0;
    SPI_SendByte(0x00);
    SPI_SendByte(0x39);
    SPI_SendByte(0x00);
    mode2_result = SPI_SendByte(0x00);
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    printf("   Mode 2 result: 0x%02X\r\n", mode2_result);
    
    // 恢复原来的 SPI Mode 3
    printf("   Restoring SPI Mode 3 (CPOL=1, CPHA=2Edge)...\r\n");
    SPI_Cmd(WIZ_SPIx, DISABLE);
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    // 4. 测试极慢的 SPI 速度
    printf("\n4. Testing very slow SPI speed...\r\n");
    SPI_Cmd(WIZ_SPIx, DISABLE);
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; // 极慢速度
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_ms(1); // 增加延时
    
    uint8_t slow_result = 0;
    SPI_SendByte(0x00);
    delay_ms(1);
    SPI_SendByte(0x39);
    delay_ms(1);
    SPI_SendByte(0x00);
    delay_ms(1);
    slow_result = SPI_SendByte(0x00);
    delay_ms(1);
    
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    printf("   Very slow speed result: 0x%02X\r\n", slow_result);
    
    // 恢复原来的速度
    SPI_Cmd(WIZ_SPIx, DISABLE);
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
    SPI_Init(WIZ_SPIx, &SPI_InitStructure);
    SPI_Cmd(WIZ_SPIx, ENABLE);
    
    // 5. 分析结果
    printf("\n5. Analysis:\r\n");
    if (mode0_result == 0x04 || mode1_result == 0x04 || mode2_result == 0x04 || slow_result == 0x04) {
        printf("   ✓ W5500 responded with correct version!\r\n");
        if (mode0_result == 0x04) printf("   → Use SPI Mode 0\r\n");
        if (mode1_result == 0x04) printf("   → Use SPI Mode 1\r\n");
        if (mode2_result == 0x04) printf("   → Use SPI Mode 2\r\n");
        if (slow_result == 0x04) printf("   → Use slower SPI speed\r\n");
    } else {
        printf("   ✗ W5500 not responding in any mode\r\n");
        printf("   Possible hardware issues:\r\n");
        printf("   - W5500 not powered (check 3.3V)\r\n");
        printf("   - 25MHz crystal not working\r\n");
        printf("   - SPI wiring problems\r\n");
        printf("   - W5500 chip damaged\r\n");
    }
    
    printf("=== Deep Diagnosis Complete ===\r\n");
}

// 添加电源检查函数
void check_w5500_power(void)
{
    printf("=== W5500 Power Check ===\r\n");
    
    // 检查复位引脚状态
    printf("Reset pin (PB7) state: %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_RESET_PORT, WIZ_RESET));
    
    // 检查中断引脚状态（应该为高电平）
    printf("INT pin (PB8) state: %d\r\n", GPIO_ReadInputDataBit(WIZ_SPIx_INT_PORT, WIZ_INT));
    
    // 手动复位测试
    printf("Testing manual reset...\r\n");
    GPIO_ResetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET);  // 拉低复位
    delay_ms(100);
    GPIO_SetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET);    // 拉高复位
    delay_ms(2000);  // 等待复位完成
    
    printf("Reset completed, testing communication...\r\n");
    
    // 简单通信测试
    GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    delay_us(10);
    uint8_t result = SPI_SendByte(0x00);
    GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS);
    
    printf("After reset - Sent: 0x00, Received: 0x%02X\r\n", result);
    
    if (result == 0xFF) {
        printf("✓ W5500 responding after reset\r\n");
    } else {
        printf("✗ W5500 still not responding\r\n");
    }
    
    printf("=== Power Check Complete ===\r\n");
}
